﻿using SocketCore.Common.Config;
using SocketCore.Common.Event;
using SocketCore.Common.Heartbeat;
using SocketCore.Common.Message;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;

namespace SocketCore.Server;

public class ServerManager
{
    /// <summary>
    /// 服务端Socket
    /// </summary>
    private Socket _serverSocket;

    /// <summary>
    /// 服务端取消令牌
    /// </summary>
    private CancellationTokenSource _cancellationTokenSource;

    /// <summary>
    /// 服务端配置
    /// </summary>
    private readonly ServerConfig _serverConfig;

    /// <summary>
    /// 心跳检测
    /// </summary>
    private readonly HeartbeatManager _heartbeatManager;

    /// <summary>
    /// 客户端管理
    /// </summary>
    private readonly ConcurrentDictionary<Socket, MessageManager> _clientMessages = new();

    /// <summary>
    /// 构造
    /// </summary>
    /// <param name="serverConfig"></param>
    public ServerManager(ServerConfig serverConfig)
    {
        _serverConfig = serverConfig ?? new ServerConfig();
        _serverConfig.EventHub.SendHeartbeatCallback = SendHeartbeatCallback;
        _serverConfig.EventHub.HeartbeatTimeout += OnClientDisconnected;
        _serverConfig.EventHub.ClientDisconnected += OnClientDisconnected;
        _heartbeatManager = new HeartbeatManager(_serverConfig, true);
    }

    /// <summary>
    /// 启动服务器Socket
    /// </summary>
    /// <returns></returns>
    public async Task StartAsync()
    {
        _cancellationTokenSource = new CancellationTokenSource();

        // 创建服务器Socket
        _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        // 启用TCP KeepAlive作为保底机制
        _heartbeatManager.SetSocketKeepAlive(_serverSocket, true, 60000, 10000);

        // 绑定IP和端口
        _serverSocket.Bind(new IPEndPoint(IPAddress.Any, _serverConfig.Port));

        // 开始监听
        _serverSocket.Listen(_serverConfig.Port);

        _serverConfig.EventHub.RaiseEvent(SocketEventType.Log, new SocketLogMessage { Level = LogLevel.Info, Message = "服务端启动成功，开始监听客户端连接" });

        // 启动心跳检测定时器
        _heartbeatManager.StartHeartbeatCheck();

        // 开始接受客户端连接
        await AcceptConnectionsAsync(_cancellationTokenSource.Token);
    }

    /// <summary>
    /// 接受客户端连接
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            try
            {
                // 异步接受客户端连接
                var clientSocket = await _serverSocket.AcceptAsync(cancellationToken);

                // 为新客户端启用TCP KeepAlive
                _heartbeatManager.SetSocketKeepAlive(clientSocket, true, 60000, 10000);

                _serverConfig.EventHub.RaiseEvent(SocketEventType.Log, new SocketLogMessage { Level = LogLevel.Info, Message = $"[{clientSocket.RemoteEndPoint}]客户端已连接" });
                _serverConfig.EventHub.RaiseEvent(SocketEventType.Connect, new SocketClientConnect { ClientInfo = clientSocket.RemoteEndPoint.ToString(), IsConnect = true });

                // 为每个客户端创建独立的MessageManager实例
                var messageManager = new MessageManager(_serverConfig, true);
                _clientMessages[clientSocket] = messageManager;
                _serverConfig.EventHub.RaiseEvent(SocketEventType.Log, new SocketLogMessage { Level = LogLevel.Debug, Message = $"ServerManager.AcceptConnectionsAsync()------" + _clientMessages.Count });

                // 初始化客户端心跳状态
                var clientState = new ClientHeartbeatState
                {
                    ReceiveCts = new CancellationTokenSource()
                };

                if (_heartbeatManager.ClientStates.TryAdd(clientSocket, clientState))
                {
                    // 启动客户端心跳发送任务
                    _ = Task.Run(() => _heartbeatManager.SendHeartbeatsAsync(clientSocket, clientState.ReceiveCts.Token), clientState.ReceiveCts.Token);

                    // 为每个客户端启动接收任务
                    _ = Task.Run(() => messageManager.ReceiveMessagesAsync(clientSocket, clientState, clientState.ReceiveCts.Token), clientState.ReceiveCts.Token);
                }
            }
            catch (OperationCanceledException)
            {
                // 服务器已停止
                break;
            }
            catch (Exception ex)
            {
                _serverConfig.EventHub.RaiseEvent(SocketEventType.Log, new SocketLogMessage { Level = LogLevel.Error, Message = $"客户端连接时发生错误：{ex.Message}", Exception = ex });
            }
        }
    }

    /// <summary>
    /// 客户端断开连接通知
    /// </summary>
    /// <param name="clientSocket"></param>
    private void OnClientDisconnected(object sender, Socket clientSocket)
    {
        _serverConfig.EventHub.RaiseEvent(SocketEventType.Connect, new SocketClientConnect { ClientInfo = clientSocket.RemoteEndPoint?.ToString(), IsConnect = false });
        _clientMessages.TryRemove(clientSocket, out var messageManager);
        // 移除客户端
        _heartbeatManager.RemoveClient(clientSocket);
        _serverConfig.EventHub.RaiseEvent(SocketEventType.Log, new SocketLogMessage { Level = LogLevel.Debug, Message = $"ServerManager.OnClientDisconnected()------" + _clientMessages.Count });
    }

    /// <summary>
    /// 发送心跳检测回调方法
    /// </summary>
    /// <param name="socket"></param>
    /// <param name="cancellationToken"></param>
    private async void SendHeartbeatCallback(Socket socket, CancellationToken cancellationToken)
    {
        if (_clientMessages.TryGetValue(socket, out var messageManager))
        {
            await messageManager.SendAsync(socket, MessageProtocol.Message.CreateHeartbeat(), cancellationToken);
        }
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="clientInfo"></param>
    /// <param name="message"></param>
    /// <returns></returns>
    public async Task SendAsync(string clientInfo, string message)
    {
        var client = _clientMessages.FirstOrDefault(x => x.Key.RemoteEndPoint.ToString().Equals(clientInfo));
        if (client.Key != null && client.Value != null)
            await client.Value.SendAsync(client.Key, MessageProtocol.Message.CreateText(message));
    }

    /// <summary>
    /// 停止服务
    /// </summary>
    public void Stop()
    {
        _cancellationTokenSource?.Cancel();
        _heartbeatManager.Dispose(); // 确保心跳管理器也被清理

        try
        {
            _serverSocket?.Close();
        }
        catch
        {
            // 忽略关闭时的异常
        }
        _serverConfig.EventHub.RaiseEvent(SocketEventType.Log, new SocketLogMessage { Level = LogLevel.Info, Message = "服务端已停止" });
    }
}